import pyglet
import math
import numpy as np

import fast_shadow as fs


def seg2D_intersect(A,B,C,D):
    Ax,Ay=A
    Bx,By=B
    Cx,Cy=C
    Dx,Dy=D

    num=(Ay-Cy)*(Dx-Cx)-(Ax-Cx)*(Dy-Cy)
    den=(Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx)

    if (den==0):
        print "Parallel !"
        return False
    if num*den<0 :
                return False
    
    from math import fabs
    if math.fabs(num)>math.fabs(den): return False
    
    return True

class Iceberg2D(object):
    def __init__(self,iName,iPoints,iFactor):
        self.name=iName
        self.nP=nP=len(iPoints)
        
        self.points=[(x*iFactor,y*iFactor) for x,y in iPoints]
        #self.points3D=[(x*1.0,y*1.0,0.0) for x,y in iPoints]
        
        
##        
        self.initSilhouette(self.points)
        self.vertices=np.zeros(nP*4,float)
        
        
        self.vertex_list=pyglet.graphics.vertex_list_indexed(nP*2,self.indices,'v2f/stream',('c3B/static', [255]*nP*6))
        #self.vertex_list.vertices=pos
        self.vertex_list.vertices=self.vertices
        

    def initSilhouette(self,iPoints):
        
        print "Iceberg :"
        print iPoints
        
        self.nP=len(iPoints)
        self.center=self.calculate_center()
        pos=[]
        
        nP=self.nP
        indices=[]
        for i in range(nP-1):
            indices.extend((i,i+nP,i+1))
            indices.extend((i,i+nP+1,i+1))
            indices.extend((i,i+nP,i+nP+1))
        indices.extend((nP-1,2*nP-1,0))
        indices.extend((nP-1,0,nP))
        indices.extend((nP-1,2*nP-2,2*nP-1))

        for i in range(nP):
            rel=[a-b for a,b in zip(iPoints[i],self.center)]
            pos.extend(rel)
            
        
        self.indices=indices
        self.silhouette=np.array(pos)
        self.contour=np.array(iPoints).ravel()
        

    def get_triangles(self):
        """ Returns a tuple of triangles making the contour of the iceberg"""
        triangles=[]
        O=self.center
        for i in range(self.nP-1):
            A=[a-b for a,b in zip(self.points[i],O)]
            B=[a-b for a,b in zip(self.points[i+1],O)]
            
            C=self.calculateC(A,B)
            #C,D=self.calculateCD(A,B)
            
            triangles.append((A,C,B))
            #triangles.append((C,D,B))
        
        A=[a-b for a,b in zip(self.points[self.nP-1],O)]
        B=[a-b for a,b in zip(self.points[0],O)]
        
        #C,D=self.calculateCD(A,B)
        C=self.calculateC(A,B)
        triangles.append((A,C,B))
        #triangles.append((C,D,B))
            
        return triangles    
    
       
        
    def calculateCD(self,A,B):
        d=self.distance(A,(0,0))
            
        C=self.extrude2D((0.,0.),A,d*0.9)
        
        d=self.distance(B,(0.,0.))
        
        D=self.extrude2D((0.,0.),B,d*0.9)
                
        return C,D
    def calculateC(self,A,B):
        maxLength=3.
        N= [a-b for a,b in zip(A,B)]   
        N2=(-N[1],N[0])
        d=self.distance(N2,(0,0))
        
        if d>maxLength:
            fact=maxLength/d
            N2=[a*fact for a in N2]
        
        
        C=[(a+b)/2+c for a,b,c in zip(A,B,N2)]
                
        return C
    
    def calculate_center(self):
        Y=X=0        
        for (x,y) in self.points:
            X+=x
            Y+=y
        
        return ((1.0*X)/(1.0*self.nP),(1.0*Y)/(1.0*self.nP))
        


    def distance(self,o,p):
        xo,yo=o
        xp,yp=p
        dx=xp-xo
        dy=yp-yo
        return math.sqrt(dx**2+dy**2)

    def draw(self, origin,distance):
        self.update_shadow(origin,distance)
        self.vertex_list.draw(pyglet.gl.GL_TRIANGLES)

    def getShadowRelVertexIndices(self,origin,range,shadowSize):
        fs.fast_shadow_rel(self.silhouette,self.vertices,self.center,0.,origin,range,shadowSize)
        return (self.indices,self.vertices)
    
    def getShadowVerticesAndIndexes(self,origin,distance):
        fs.fast_shadow_abs(self.silhouette,self.vertices,self.center,0.,origin,distance)

        
        return (self.indices,self.vertices)
    

    def isBlocking(self,obs,target):
        """ Checks if this iceberg is blocking the view from observer
        to target.
        Takes two tuples with minimum length 2 as arguments
        """
        A=obs[0:2]
        B=target[0:2]
        SegA=self.points[0]

        for i in range(1,len(self.points)):
            SegB=self.points[i]
            if seg2D_intersect(A,B,SegA,SegB):
                return True
            SegA=SegB
        return False
 
 
if __name__ == '__main__':
    ic=Iceberg2D("Toto",((30,50),(30,100),(100,100),(100,20)),0.1)
    
    w = open('shadow.txt','w')
    seq=ic.update_shadow((0.,40.),200.)
    lst=[(seq[2*i],seq[2*i+1]) for i in range(0,len(seq)//2)]
        
    for p,q in zip(ic.points,lst):
        w.write("%d;%d\n"%(p))
        w.write("%d;%d\n"%(q))
    
    
    
    w.close()
    #print window.space_to_screen(window.screen_to_space((100,10)))

              
